package com.ruoyi.mongo.cet4.repository.impl;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@NoRepositoryBean
public class CustomSimpleMongoRepository<T, ID> implements PagingAndSortingRepository<T, ID> {

    // 实体类型
    private final Class<T> domainType;
    // MongoDB操作核心组件
    private final MongoOperations mongoOps;
    // 当前操作的集合名称
    private String collectionName;

    // 构造器：初始化必要依赖
    public CustomSimpleMongoRepository(Class<T> domainType, MongoOperations mongoOps) {
        Assert.notNull(domainType, "实体类类型不能为null");
        Assert.notNull(mongoOps, "MongoOperations不能为null");

        this.domainType = domainType;
        this.mongoOps = mongoOps;
        // 默认为实体类对应的集合名（类名首字母小写）
        this.collectionName = mongoOps.getCollectionName(domainType);
    }

    /**
     * 动态设置操作的集合名称
     */
    public void setTargetCollection(String collectionName) {
        Assert.hasText(collectionName, "集合名称不能为空");
        this.collectionName = collectionName;
    }

    /**
     * 保存单个实体（新增或更新）
     */
    public <S extends T> S save(S entity) {
        Assert.notNull(entity, "保存的实体不能为null");
        mongoOps.save(entity, collectionName);
        return entity;
    }

    /**
     * 批量保存实体
     */
    public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
        Assert.notNull(entities, "实体集合不能为null");

        // 转换为List便于处理
        List<S> entityList = StreamSupport.stream(entities.spliterator(), false)
                .collect(Collectors.toList());

        // 批量保存（MongoDB支持批量操作优化）
        if (!entityList.isEmpty()) {
            mongoOps.insert(entityList, collectionName);
        }
        return entityList;
    }

    /**
     * 根据ID查询实体
     */
    public Optional<T> findById(ID id) {
        Assert.notNull(id, "ID不能为null");
        T entity = mongoOps.findById(id, domainType, collectionName);
        return Optional.ofNullable(entity);
    }

    /**
     * 判断ID是否存在
     */
    public boolean existsById(ID id) {
        Assert.notNull(id, "ID不能为null");
        Query query = Query.query(Criteria.where("_id").is(id));
        return mongoOps.exists(query, collectionName);
    }

    /**
     * 查询所有实体
     */
    public Iterable<T> findAll() {
        return mongoOps.findAll(domainType, collectionName);
    }

    /**
     * 根据ID集合查询
     */
    public Iterable<T> findAllById(Iterable<ID> ids) {
        Assert.notNull(ids, "ID集合不能为null");

        List<ID> idList = StreamSupport.stream(ids.spliterator(), false)
                .collect(Collectors.toList());

        if (idList.isEmpty()) {
            return new ArrayList<>();
        }

        Query query = Query.query(Criteria.where("_id").in(idList));
        return mongoOps.find(query, domainType, collectionName);
    }

    /**
     * 统计总记录数
     */
    public long count() {
        return mongoOps.count(new Query(), collectionName);
    }

    /**
     * 根据ID删除
     */
    public void deleteById(ID id) {
        Assert.notNull(id, "ID不能为null");
        Query query = Query.query(Criteria.where("_id").is(id));
        mongoOps.remove(query, collectionName);
    }

    /**
     * 删除实体
     */
    public void delete(T entity) {
        Assert.notNull(entity, "删除的实体不能为null");
        mongoOps.remove(entity, collectionName);
    }

    /**
     * 批量删除指定ID的实体
     */
    public void deleteAllById(Iterable<? extends ID> ids) {
        Assert.notNull(ids, "ID集合不能为null");

        List<ID> idList = StreamSupport.stream(ids.spliterator(), false)
                .collect(Collectors.toList());

        if (!idList.isEmpty()) {
            Query query = Query.query(Criteria.where("_id").in(idList));
            mongoOps.remove(query, collectionName);
        }
    }

    /**
     * 批量删除实体
     */
    public void deleteAll(Iterable<? extends T> entities) {
        Assert.notNull(entities, "实体集合不能为null");
        entities.forEach(this::delete);
    }

    /**
     * 删除集合中所有数据
     */
    public void deleteAll() {
        mongoOps.remove(new Query(), collectionName);
    }

    /**
     * 排序查询
     */
    @Override
    public Iterable<T> findAll(Sort sort) {
        Assert.notNull(sort, "排序条件不能为null");
        Query query = new Query().with(sort);
        return mongoOps.find(query, domainType, collectionName);
    }

    /**
     * 分页查询
     */
    @Override
    public Page<T> findAll(Pageable pageable) {
        Assert.notNull(pageable, "分页条件不能为null");

        // 构建分页查询
        Query query = new Query().with(pageable);
        List<T> content = mongoOps.find(query, domainType, collectionName);

        // 计算总条数
        long total = mongoOps.count(Query.of(query).limit(-1).skip(-1), collectionName);

        // 构建分页结果
        return new org.springframework.data.domain.PageImpl<>(content, pageable, total);
    }

    /**
     * 扩展：按字段条件查询
     */
    public List<T> findBy(String field, Object value) {
        Assert.hasText(field, "字段名不能为空");
        Assert.notNull(value, "字段值不能为null");

        Query query = Query.query(Criteria.where(field).is(value));
        return mongoOps.find(query, domainType, collectionName);
    }
}

